/**
 * Copyright (C) 2009-2012, KingHool.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses.
 */
package com.kinghool.smodel.def;

import org.jdom.Element;

import com.kinghool.ebos.commons.utils.Assert;
import com.kinghool.ebos.commons.utils.Utils;
import com.kinghool.smodel.utils.JDomUtils;

/**
 * 
 * @Author Allen Deng(dengtailin@gmail.com) 
 */
public class XmlModelDefinition extends TreeModelDefinition {

	protected boolean isTextCData = false;
	protected boolean isAllTextCData = false;
	
	public XmlModelDefinition(String id) {
		super(id);
	}
	
	public static XmlModelDefinition createDefaultXmlModelDefinition(String id) {
		return createDefaultXmlModelDefinition(id, null);
	}
	
	public static XmlModelDefinition createDefaultXmlModelDefinition(String id, XmlModelDefinition parent) {
		XmlModelDefinition modelDef = new XmlModelDefinition(id);
		modelDef.setCaseSensitive(true);
		modelDef.setIgnoreCheck(true);
		modelDef.setParent(parent);
		return modelDef;
	}
	
	public static XmlModelDefinition getNotNullChildXmlModelDefinition(String childId, XmlModelDefinition modelDefinition) {
		XmlModelDefinition rtnChildModelDef = createDefaultXmlModelDefinition(childId, modelDefinition);
		if (modelDefinition != null) {
			XmlModelDefinition childModelDef = modelDefinition.getChildModelDefinition(childId);
			if (childModelDef != null) {
				rtnChildModelDef = childModelDef;
			}
		}
		return rtnChildModelDef;
	}
	
	public XmlModelDefinition getRoot(){
		return (XmlModelDefinition) super.getRoot();
	} 
	
	public XmlModelDefinition getParent() {
		return (XmlModelDefinition) super.getParent();
	} 

	public void setParent(TreeModelDefinition parent) {
		checkType(parent, true);
		super.setParent(parent);
	} 
	 
	public XmlModelDefinition getChildModelDefinition(String childFullName) {
		return (XmlModelDefinition) super.getChildModelDefinition(childFullName);
	} 
	
	public void installChild(TreeModelDefinition child) {
		checkType(child, false);
		super.installChild(child);
	}
	
	protected void checkType(TreeModelDefinition modelDefinition, boolean nullable) {
		if (!(modelDefinition instanceof XmlModelDefinition)) {
			if (!(modelDefinition == null && nullable)) {
				throw new IllegalArgumentException("Illegal modeldefinition type: it should be XmlModelDefinition.");
			} 
		}
	}


	public Element createDefaultElement(String name, boolean full) {
		Element element = new Element(name);
		createElement(element, this, full);
		return element;
	}
	
	protected void createElement(Element element, XmlModelDefinition modelDef, boolean full) {  
		for (String attr : modelDef.propValues.keySet()) {
			if (full || Assert.isNotNullNotEmpty(attr)) {
				Object defaultValue = modelDef.propValues.get(attr); 
				element.setAttribute(attr, Utils.getNotNullAndTrimString(defaultValue == null ? null : defaultValue.toString()));
			}
		}
		for (String childName : getChildrenSequence()) {
			XmlModelDefinition childSchema = modelDef.getChildModelDefinition(childName);
			if (childSchema != null && (full || childSchema.isMandantory())) {
				Element childElement = childSchema.createDefaultElement(childName, full);
				JDomUtils.insertChild(element, childElement, modelDef.getChildrenSequence());  
			}
		}
	}

	public boolean isTextCData() {
		return isTextCData;
	}

	public void setTextCData(boolean isTextCData) {
		this.isTextCData = isTextCData;
	}

	public boolean isAllTextCData() {
		if (getParent() != null) {
			return getParent().isAllTextCData();
		}
		return isAllTextCData;
	}

	public void setAllTextCData(boolean isAllTextCData) {
		if (getParent() != null) {
		   getParent().setAllTextCData(isAllTextCData);
		} else {
			this.isAllTextCData = isAllTextCData;
		}
	}
}
